#!/usr/bin/env python
## @example example2.py
#  @see example2.c

#####################################################################
# Example for testing two implementation of geodesic reconstruction #
#  - A fast way using fifo                                          #
#  - A naive way using basic mathematical definition                #
#####################################################################


import time

from fulguro import *

### BENCH PROCEDURES #########################################################
def benchmark(function,nbiter,*args):
    t=time.time()
    for i in range(nbiter):
        function(*args)
    t2=time.time()
    return ((t2-t)*1000)/nbiter

### PROCEDURES #########################################################

#######################################
### Geodesic Reconstruction by dilation
#######################################
def geodesic_rec_dilate(immarker,immask,nhb):
    if nhb.connexity==FLGR_8_CONNEX:
        nhb = FLGR_Data2D(3,3,nhb.spp,immarker.type,FLGR_RECT,FLGR_8_CONNEX)
        
    elif nhb.connexity==FLGR_6_CONNEX:
        nhb = FLGR_Data2D(3,3,nhb.spp,immarker.type,FLGR_HEX,FLGR_6_CONNEX)
        
    else:
        nhb = FLGR_Data2D(3,3,nhb.spp,immarker.type,FLGR_CROSS,FLGR_4_CONNEX);
        
    imtmp1 = FLGR_Data2D(immarker)
    imtmp2 = FLGR_Data2D(immarker)
    
    flgr2d_copy(imtmp2,immarker)
    flgr2d_dilate(imtmp1,imtmp2,nhb)
    flgr2d_arith_inf(imtmp2,immask,imtmp1)

    vol1 = flgr2d_measure_volume(immarker)[0]
    vol2 = flgr2d_measure_volume(imtmp2)[0]
 
    while (vol1 != vol2):
        vol1 = vol2
        flgr2d_copy(immarker,imtmp2)
        flgr2d_dilate(imtmp1,imtmp2,nhb)
        flgr2d_arith_inf(imtmp2,immask,imtmp1)
        vol2 = flgr2d_measure_volume(imtmp2)[0]
  

def geodesic_rec_dilate2(immarker,immask,nhb):
    imtmp = FLGR_Data2D(immarker)

    while not(imtmp == immarker):
        flgr2d_copy(imtmp,immarker)
        flgr2d_geodesic_dilate_8_connexity(immarker, immask)

 
#######################################
### Geodesic Reconstruction by Erosion
#######################################
def geodesic_rec_erode(immarker,immask,nhb):
    if nhb.connexity==FLGR_8_CONNEX:
        nhb = FLGR_Data2D(3,3,nhb.spp,immarker.type,FLGR_RECT,FLGR_8_CONNEX)
        
    elif nhb.connexity==FLGR_6_CONNEX:
        nhb = FLGR_Data2D(3,3,nhb.spp,immarker.type,FLGR_HEX,FLGR_6_CONNEX)
        
    else:
        nhb = FLGR_Data2D(3,3,nhb.spp,immarker.type,FLGR_CROSS,FLGR_4_CONNEX);
        
    imtmp1 = FLGR_Data2D(immarker)
    imtmp2 = FLGR_Data2D(immarker)
    
    flgr2d_copy(imtmp2,immarker)
    flgr2d_erode(imtmp1,imtmp2,nhb)
    flgr2d_arith_sup(imtmp2,immask,imtmp1)
    
    while not(immarker == imtmp2):
        flgr2d_copy(immarker,imtmp2)
        flgr2d_erode(imtmp1,imtmp2,nhb)
        flgr2d_arith_sup(imtmp2,immask,imtmp1)

def geodesic_rec_erode2(immarker,immask,nhb):
    imtmp = FLGR_Data2D(immarker)

    while not(imtmp == immarker):
        flgr2d_copy(imtmp,immarker)
        flgr2d_geodesic_erode_8_connexity(immarker, immask)

#######################################
### Geodesic Reconstruction by Openning
#######################################
def geodesic_rec_open(imdest,imin,nhb):
    flgr2d_erode(imdest,imin,nhb)
    geodesic_rec_dilate(imdest,imin,nhb)

#######################################
### Geodesic Reconstruction by Closing
#######################################
def geodesic_rec_close(imdest,imin,nhb):
    flgr2d_dilate(imdest,imin,nhb)
    geodesic_rec_erode(imdest,imin,nhb)

#######################################
### Geodesic Open Tophat
#######################################
def geodesic_rec_open_tophat(imdest,imin,nhb):
    geodesic_rec_open(imdest,imin,nhb)
    flgr2d_arith_sub(imdest,imin,imdest)

#######################################
### Geodesic Open Tophat
#######################################
def geodesic_rec_close_tophat(imdest,imin,nhb):
    geodesic_rec_close(imdest,imin,nhb)
    flgr2d_arith_sub(imdest,imdest,imin)


def printImage(imin):
    a = flgr2d_export_raw(imin)
    w = imin.size_x
    for i in range(imin.size_y-1):
        print a[i*w:(i+1)*w]
    print

##################################################################
### MAIN #########################################################
##################################################################


imin = flgr2d_load_pgm('../../images/gray/lena.pgm')
imDest1 = FLGR_Data2D(imin)
imDest2 = FLGR_Data2D(imin)
imDest3 = FLGR_Data2D(imin)
imDest4 = FLGR_Data2D(imin)
imDest5 = FLGR_Data2D(imin)
nhb = FLGR_Data2D(11,11,imin.spp,imin.type,FLGR_RECT,FLGR_8_CONNEX)



flgr2d_erode(imDest1, imin, nhb)
flgr2d_copy(imDest2,imDest1)
flgr2d_copy(imDest3,imDest1)
flgr2d_copy(imDest4,imDest1)
flgr2d_copy(imDest5,imDest1)



speed = benchmark(flgr2d_geodesic_reconstruct_dual,20,imDest1,imin,nhb.connexity)
print 'Fast Dual Geodesic reconstruction time :',speed,'ms'

speed = benchmark(flgr2d_geodesic_reconstruct_dilate,20,imDest2,imin,nhb.connexity)
print 'Fast Geodesic reconstruction by dilation time :',speed,'ms'

speed = benchmark(geodesic_rec_dilate,100,imDest3,imin,nhb)
print 'Naive Geodesic reconstruction time :',speed,'ms'

speed = benchmark(geodesic_rec_dilate2,100,imDest4,imin,nhb)
print 'Naive partial C layer Geodesic reconstruction time :',speed,'ms'

speed = benchmark(flgr2d_geodesic_reconstruct_dilate_parallel,100,imDest5,imin,nhb.connexity)
print 'Naive C layer Geodesic reconstruction time :',speed,'ms'




if imDest1==imDest2 and imDest2==imDest3 and imDest3==imDest4 and imDest4==imDest5:
    print "Images are equals :)"
else:
    print "Images are not equals :("
    


flgr_display(imDest1,"fast_dual",imDest2,"fast",imDest3,"naive",imDest4,"naive_partial_c",imDest5,"naive_c")
